home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / spoc88 / cengn / dirtree.c < prev    next >
Text File  |  1988-06-22  |  7KB  |  169 lines

  1. /************************************************************
  2. DIRTREE.C - by Jake Richter
  3.  
  4.     Provides core routines for traversing a directory tree, 
  5. using a "bottom-most first" algorithm.
  6.     As presented, code will search the directory tree and 
  7. for each directory found, will call a routine called
  8. SearchEngine(), which in turn will process certain files in
  9. that directory in some fashion.
  10. ************************************************************/ 
  11. #include "dos.h"         /* Contains ffblk structure.      */
  12. #include "dir.h"         /* Required by findfirst, findnext,
  13.                             getcwd.                        */ 
  14.  
  15.  
  16. /************************************************************
  17.                     Program Definitions
  18. ************************************************************/
  19. #define MAXDIRDEPTH 15   /* Maximum directory depth.       */
  20. #define FALSE       0
  21. #define TRUE        !FALSE
  22. typedef struct ffblk FFBLK;
  23.  
  24.  
  25. /************************************************************
  26.                  Mandatory Global Declarations
  27. ************************************************************/
  28.                                  /* Declare a file info block 
  29.                                     for each potential 
  30.                                     directory level.       */
  31. static  FFBLK   fileBlock[MAXDIRDEPTH];
  32. static  int     curDepth = -1;   /* Depth indicator.       */
  33. static  int     done;            /* Used as a local flag in
  34.                                     the recursive function. 
  35.                                     Declared globally to 
  36.                                     minimize stack usage 
  37.                                     incurred by recursion. */
  38. static  char    *filename;       /* Filename mask for the
  39.                                     Search Engine.         */
  40. static  char    attribute;       /* Attribute for engine.  */
  41. static  void    (*funcPtr)();    /* Function ptr for engine*/
  42.  
  43. /************************************************************
  44.   void GetNextDir()
  45.  
  46.     This is the recursive routine that traverses the 
  47. directory tree.
  48. ************************************************************/
  49. static void    GetNextDir()
  50. {
  51.   curDepth++;  /* Everytime this code gets called, we go down 
  52.                   a level in the tree.                     */
  53.  
  54.                /* We can't go too deep because we have only 
  55.                   so many file block structures.           */
  56.   if (curDepth >= MAXDIRDEPTH)
  57.     return;
  58.  
  59.                /* Since this section is encountered only when 
  60.                   going down to a new level, (re)initialize
  61.                   the current level's file block by calling 
  62.                   findfirst. findfirst and findnext return a 
  63.                   TRUE (non-zero) value when all files in the 
  64.                   current directory have been "found". A 
  65.                   separate block is needed for each level 
  66.                   because previously determined information 
  67.                   (set by findfirst and subsequent findnext 
  68.                   calls) must be maintained until an entire 
  69.                   directory level has been searched.       */ 
  70.  
  71.   done = findfirst("*.*", &fileBlock[curDepth], FA_DIREC);
  72.  
  73.                /* It is important to remember that "." and 
  74.                   ".." are valid directory names, but that 
  75.                   they also should be ignored while 
  76.                   traversing the tree. The following 
  77.                   conditional in psuedo-code: 
  78.  
  79.   while((not all files have been "found")
  80.       AND (((the currently found file is really a directory)
  81.          AND (this directory starts with "."))
  82.       OR (this the file is not really a directory)))
  83.     then 
  84.        get the information of the next file found and check 
  85.        it against the previous conditions.
  86.  
  87.                                                            */
  88.   while(!done
  89.          && (((fileBlock[curDepth].ff_attrib == FA_DIREC)
  90.            &&  (fileBlock[curDepth].ff_name[0] == '.'))
  91.          || (fileBlock[curDepth].ff_attrib != FA_DIREC)))
  92.     done = findnext(&fileBlock[curDepth]);
  93.  
  94.                /* When we get to this point, one of two 
  95.                   things must be true: either we are out of 
  96.                   files, in which case (done == TRUE), or we 
  97.                   have found the first valid directory name 
  98.                   in the current directory.                */
  99.   if (!done)
  100.     {          /* Since we have found a valid directory, go 
  101.                   to it and repeat the above.              */
  102.     chdir(fileBlock[curDepth].ff_name);
  103.     GetNextDir(); /* Call this routine again.              */
  104.     chdir("..");  /* Move back up to the correct directory 
  105.                      for this level.                       */
  106.     curDepth--;   /* Also adjust the depth gauge.          */
  107.     }
  108.   else
  109.     {          /* There are no valid directories below
  110.                   the current, therefore this one must be at 
  111.                   the end of a branch and should be
  112.                   processed.                               */
  113.  
  114.                /* Process this directory.                  */
  115.     SearchEngine(filename, attribute, funcPtr);
  116.     return;    /* We're done at this level.                */
  117.     }
  118.  
  119.                /* Get the information about the next file. */
  120.   done = findnext(&fileBlock[curDepth]);
  121.  
  122.                /* We are now searching for all other 
  123.                   directories that might be below the current 
  124.                   one.                                     */
  125.   while (1)
  126.     {          /* This "while" is the same as the previous.*/
  127.     while (!done
  128.             && (((fileBlock[curDepth].ff_attrib == FA_DIREC)
  129.              && (fileBlock[curDepth].ff_name[0] == '.'))
  130.              || (fileBlock[curDepth].ff_attrib != FA_DIREC)))
  131.       done = findnext(&fileBlock[curDepth]);
  132.  
  133.     if (!done)
  134.       {        /* Drop down to the next level.             */
  135.       chdir(fileBlock[curDepth].ff_name);
  136.       GetNextDir(); /* Call this routine again.            */
  137.       chdir("..");  /* Move back up.                       */
  138.       curDepth--;
  139.                /* Prepare for the "while" above.           */
  140.       done = findnext(&fileBlock[curDepth]);
  141.       }
  142.     else       /* No more files to be found. Break out of 
  143.                   outer loop.                              */
  144.       break;
  145.     }
  146.                /* Process the current directory since all the 
  147.                   ones below it have already been processed*/
  148.   SearchEngine(filename, attribute, funcPtr);
  149.   return;      /* Bye.                                     */
  150. }
  151.  
  152. /************************************************************
  153.   void DirTree(fname, attr, proc)
  154.  
  155.     This routine sets up the call for the recursive tree
  156. search routine and the search engine.
  157. ************************************************************/
  158. void DirTree(fname, attr, proc)
  159. char  *fname;
  160. char  attr;
  161. void  (*proc)();
  162. {
  163.   filename = fname;     /* Set global variables for Engine.*/
  164.   attribute = attr;
  165.   funcPtr = proc;
  166.   GetNextDir();         /* Initiate recursive search.      */
  167.   return;
  168. }
  169.